package com.ng.common.fileupload;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

import javax.imageio.ImageIO;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import com.ng.common.exception.NgException;
import com.ng.common.fileupload.entity.UploadFileInfoEntity;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.util.HexUtil;

/**
 * 阿拉汀文件公共上传下载服务
 * @author lyf
 *
 */
public interface GsFileStorage {
	Logger logger = LoggerFactory.getLogger(GsFileStorage.class);
	/**
	 * 返回类型
	 * @return
	 */
	public String getType();
	
	/**
	 * 上传文件 
	 * @param file
	 * @return
	 */
	public UploadFileInfoEntity uploadFile(MultipartFile file) ;
	
	
	/**
	 * 上传本地文件
	 * @param file
	 * @return
	 */
	public UploadFileInfoEntity uploadFile(File file);
	
	/**
	 * 下载文件 默认当fastdfs 和ftp 的时候应该通过nginx代理过去直接下载 而不是通过此犯法,但此方法依然要实现下载的业务
	 * @param entity 实体
	 * @param out 输出流 
	 */
	public void downFile(UploadFileInfoEntity entity , OutputStream out);
	
	/**
	 * 删除文件 
	 * @param entity
	 * @return
	 */
	public boolean deleteFile(UploadFileInfoEntity entity);
	 
	
	/**
	 * 校验文件
	 * @param data
	 * @param suffix
	 * @throws IOException 
	 */
	public default byte[] validatorFile(byte[] data , String suffix)  {
		
		// 如果是图片 则图片另存 其他格式读取头信息 判断格式是否正确
		if(suffix.toLowerCase().endsWith("jpg") || suffix.toLowerCase().endsWith("png")) {
			
			BufferedImage bi;
			try {
				bi = ImageIO.read(new ByteArrayInputStream(data));
				
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				
				cn.hutool.core.util.ImageUtil.write(bi, suffix, out);
				
				out.flush();
				
				return out.toByteArray();
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				logger.error("validator image error" , e);
				throw new NgException("图片检测实际格式和后缀不符,请打开图片另存为PNG或者JPG格式后再进行上传。");
			} 
			
		} else if(suffix.toLowerCase().endsWith("pdf")){
			if(data.length < 28) {
				throw new NgException("文件真实格式校验异常,请检查文件格式。");
			}
			
			// 读取文件头
			byte[] contentTypeHeader = new byte[28];
					
			System.arraycopy(data, 0, contentTypeHeader, 0, 28);
			 
			String type = FileTypeUtil.getType(HexUtil.encodeHexStr(contentTypeHeader, false));
			
			if(!type.equals("pdf")) {
				throw new NgException("PDF文件检测实际格式和后缀不符,请打开文件另存后再进行上传。");
			}
		} else if(suffix.toLowerCase().endsWith("docx")) {
			// docx 直接读取一下  
			try {
				XWPFDocument document = new XWPFDocument(new ByteArrayInputStream(data));
				
				document.close();
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				logger.error("docx read error." , e);
				throw new NgException("WORD文件检测实际格式和后缀不符,请打开文件另存后再进行上传。");
			} 
		} else if(suffix.toLowerCase().endsWith("doc")) {
			// docx 直接读取一下  
			try { 
				HWPFDocument doc = new HWPFDocument(new ByteArrayInputStream(data));
				 
				doc.close();
				 
			} catch (Exception e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				logger.error("doc read error." , e);
				throw new NgException("WORD文件检测实际格式和后缀不符,请打开文件另存后再进行上传。");
			} 
		} else if(suffix.toLowerCase().endsWith("xlsx")) {
			Workbook wb;
			try {
				wb = new XSSFWorkbook(new ByteArrayInputStream(data));
				wb.getNumberOfSheets(); 
				
				wb.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				logger.error("xlsx read error." , e);
				throw new NgException("Excel文件检测实际格式和后缀不符,请打开文件另存后再进行上传。");
			}//StreamingReader.builder().rowCacheSize(500).bufferSize(20480) .open();
			
			
		} else if(suffix.toLowerCase().endsWith("xls")) {
			Workbook wb;
			try {
				wb = new HSSFWorkbook(new ByteArrayInputStream(data));
				wb.getNumberOfSheets(); 
				
				wb.close();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
				logger.error("xls read error." , e);
				throw new NgException("Excel文件检测实际格式和后缀不符,请打开文件另存后再进行上传。");
			}//StreamingReader.builder().rowCacheSize(500).bufferSize(20480) .open();
			
			
		}
		
		
		return data;
	} 

}
